include('shared.lua')

if (not BASS) then pcall(require, "BASS") end

-- Drawing defaults
surface.CreateFont("arial",30,400,true,false,"StreamRadio_Default") //akbar
surface.CreateFont("arial",60,400,true,false,"StreamRadio_Big")
local BackgroundColor = Color(0, 64, 128, 255)
local TextColor = Color(0, 0, 0, 255)
local EntryColor = Color(128, 100, 0, 255)
local EntryActiveColor = Color(0, 100, 0, 255)
local ButtonColor = Color(0, 128, 128, 255)
local ButtonActiveColor = Color(128,128, 64, 255)
local SpectrumBarsColor = Color(128, 0, 0, 255)
local SpectrumTopColor = Color(128, 64, 0, 255)

function ENT:Initialize()
	self.Channel = nil
	self.ChannelError = nil
	self.SoundSource = ""
	self.SoundName = ""

	self.ChannelCallback = function(Channel, Error)
		if (self.Channel) then
			self.Channel:stop()
			self.Channel = nil
		end
		if (Channel and self:NBool("Mode") == true) then
			self.Channel = Channel
			self.Channel:play()
		elseif (not Channel and Error and self:NBool("Mode") == true) then
			self.ChannelError = Error
		end
	end
	self.SpectrumTable = {}
end

function ENT:Think()
	if (BASS) then
		local Mode = self:NBool("Mode")
		local Sound = self:NString("SoundSource")
		local SoundName = self:NString("SoundName")
		local Levels = {0,0,0,0,0,0,0,0}

		if (Mode == false) then
			if (self.Channel) then
				self.Channel:stop()
				self.Channel = nil
			end

			self.SoundSource = ""
			self.SoundName = ""

		elseif (Mode == true and type(Sound) == "string" and Sound ~= "") then
			if (Sound ~= self.SoundSource) then
				if (self.Channel) then
					self.Channel:stop()
					self.Channel = nil
				end

				BASS.StreamFileURL(Sound, -1, self.ChannelCallback)
				self.SoundSource = Sound
				self.SoundName = SoundName
				self.ChannelError = nil
			end

			if (self.Channel) then
				local Pos = self.Entity:GetPos()
				Pos.z = -Pos.z
				local For = self.Entity:GetAngles():Forward()
				local Vel = self.Entity:GetVelocity() * 0.01

				self.Channel:set3dposition(Pos, For, Vel)
				self.Channel:setvolume(self:NFloat("Volume")/100)
				
				Levels = self.Channel:fft2048()

				for i=1, 8, 1 do
					self:NInt(tostring(i), math.Round(math.Clamp(Levels[i] * 1000, 0, 100)))
					//print(self:NInt(tostring(i)))
				end
			end
		end
	end
	self.Entity:NextThink(CurTime()+0.01)
	return true
end

function ENT:Draw()
	self.Entity:DrawModel()

	self:DrawOverlay()
end

function ENT:DrawOverlay()
	local Pos = self.Entity:GetPos() + (self.Entity:GetForward() * 2.4) + (self.Entity:GetUp() * (3.7 + 3)) + (self.Entity:GetRight() * 7)
	local Ang = self.Entity:GetAngles()
	local Rot = Vector(-90,90,0)
	Ang:RotateAroundAxis(Ang:Right(), Rot.x)
	Ang:RotateAroundAxis(Ang:Up(), Rot.y)
	Ang:RotateAroundAxis(Ang:Forward(), Rot.z)

	if (BASS) then
		local Mode = self:NBool("Mode")

		local Cx, Cy = 0, 0
		local C1 = false

		local trace = LocalPlayer():GetEyeTraceNoCursor()
		if (trace.Entity == self.Entity) then
			local HitPos = WorldToLocal(trace.HitPos, Angle(0,0,0), Pos, Ang)
			Cx = (HitPos.x / 14) * 700
			Cy = (-HitPos.y / 6) * 300
			C1 = true
		end

		cam.Start3D2D(Pos, Ang, 0.02)
			draw.RoundedBox(16, 0, 0, 700, 300, BackgroundColor)

			if (Mode == false) then
				draw.RoundedBox(16, 20, 20, 400, 260, ButtonColor)

				-- List box
				surface.SetFont("StreamRadio_Default")
				surface.SetTextColor(EntryColor)

				-- Entry 1
				if (self:NInt("ActiveEntry") == 1) then draw.RoundedBox(16, 34, 30, 368, 40, EntryActiveColor ) end
				surface.SetTextPos(36, 20)
				surface.DrawText(self:NString("Entry1"))

				-- Entry 2
				if (self:NInt("ActiveEntry") == 2) then draw.RoundedBox(16, 34, 94, 368, 40, EntryActiveColor ) end
				surface.SetTextPos(36, 85)
				surface.DrawText(self:NString("Entry2"))

				-- Entry 3
				if (self:NInt("ActiveEntry") == 3) then draw.RoundedBox(16, 34, 159, 368, 40, EntryActiveColor ) end
				surface.SetTextPos(36, 150)
				surface.DrawText(self:NString("Entry3"))

				-- Entry 4
				if (self:NInt("ActiveEntry") == 4) then draw.RoundedBox(16, 34, 224, 368, 40, EntryActiveColor ) end
				surface.SetTextPos(36, 215)
				surface.DrawText(self:NString("Entry4"))

				-- Up Button
				if (C1 and Cx > 420 and Cx < 520 and Cy > 20 and Cy < 120) then
					draw.RoundedBox(16, 420, 20, 100, 100, ButtonActiveColor)
				else
					draw.RoundedBox(16, 420, 20, 100, 100, ButtonColor)
				end
				surface.SetTextPos(420, 30)
				surface.DrawText("Up")

				-- Down Button
				if (C1 and Cx > 420 and Cx < 520 and Cy > 180 and Cy < 280) then
					draw.RoundedBox(16, 420, 180, 100, 100, ButtonActiveColor)
				else
					draw.RoundedBox(16, 420, 180, 100, 100, ButtonColor)
				end
				surface.SetTextPos(420, 190)
				surface.DrawText("Down")

				-- Play Button
				if (C1 and Cx > 520 and Cx < 680 and Cy > 20 and Cy < 280) then
					draw.RoundedBox(16, 520, 20, 160, 260, ButtonActiveColor)
				else
					draw.RoundedBox(16, 520, 20, 160, 260, ButtonColor)
				end
				surface.SetTextPos(530, 130)
				surface.DrawText("Play")
			elseif (Mode == true) then
				if (self.Channel) then
					surface.SetFont("StreamRadio_Big")
					surface.SetTextColor(TextColor)

					surface.SetTextPos(16, 0)
					surface.DrawText(self.SoundName)

					surface.SetTextPos(100, 80)
					surface.DrawText("Playing ...")

					if (C1 and Cx > 400 and Cx < 650 and Cy > 60 and Cy < 160) then
						draw.RoundedBox(16, 400, 60, 250, 100, ButtonActiveColor)
					else
						draw.RoundedBox(16, 400, 60, 250, 100, ButtonColor)
					end

					surface.SetFont("StreamRadio_Default")
					surface.SetTextColor(TextColor)

					surface.SetTextPos(410, 70)
					surface.DrawText("Stop Stream")

					local Bars = self:NInt("Spectrum_Bars")
					local Steps = 1024 / Bars
					local Size = 1024

					local Height = 280

					local Levels = self.Channel:fft2048()

					for i = 1, Size, Steps do
						local Size = math.Clamp(Levels[math.Round(i)] * 1120, 0, 140)

						surface.SetDrawColor(SpectrumBarsColor)
						surface.DrawRect(((i + 14) / Steps) * (670/1024)*Steps, Height - Size, (670/1024)*Steps, Size)

						local SpecVal = self.SpectrumTable[math.Round(i)] or 0

						SpecVal = SpecVal - 0.5
						if (SpecVal < Size) then SpecVal = Size end
						self.SpectrumTable[math.Round(i)] = SpecVal

						surface.SetDrawColor(SpectrumTopColor)
						surface.DrawRect(((i + 14) / Steps) * (670/1024)*Steps, Height - SpecVal - 2, (670/1024)*Steps, 2)
					end
				else
					surface.SetFont("StreamRadio_Big")
					surface.SetTextColor(TextColor)

					surface.SetTextPos(16, 0)
					surface.DrawText(self.SoundName)

					if (self.ChannelError) then
						surface.SetTextPos(30, 170)
						surface.DrawText("Error Connecting: " .. self.ChannelError)

						if (C1 and Cx > 400 and Cx < 650 and Cy > 20 and Cy < 120) then
							draw.RoundedBox(16, 400, 60, 250, 100, ButtonActiveColor)
						else
							draw.RoundedBox(16, 400, 60, 250, 100, ButtonColor)
						end

						surface.SetFont("StreamRadio_Default")
						surface.SetTextColor(TextColor)

						surface.SetTextPos(410, 70)
						surface.DrawText("Return")
					else
						surface.SetTextPos(100, 80)
						surface.DrawText("Connecting ...")

						if (C1 and Cx > 400 and Cx < 650 and Cy > 20 and Cy < 120) then
							draw.RoundedBox(16, 400, 60, 250, 100, ButtonActiveColor)
						else
							draw.RoundedBox(16, 400, 60, 250, 100, ButtonColor)
						end

						surface.SetFont("StreamRadio_Default")
						surface.SetTextColor(TextColor)

						surface.SetTextPos(410, 70)
						surface.DrawText("Stop Try")
					end
				end
			end
		cam.End3D2D()
	else
		cam.Start3D2D(Pos, Ang, 0.02)
			draw.RoundedBox(16, 0, 0, 700, 300, BackgroundColor)

			surface.SetFont("StreamRadio_Big")
			surface.SetTextColor(TextColor)

			surface.SetTextPos(0, 0)
			surface.DrawText("GM_BASS module not installed")

			surface.SetTextPos(0, 70)
			surface.DrawText("Radio not available")
		cam.End3D2D()
	end
end

function ENT:OnRemove()
	if (self.Channel) then
		self.Channel:stop()
		self.Channel = nil
	end
end

if (BASS) then
	local function StreamRadio_BassReposition()
		local Ply = LocalPlayer()

		local Pos = Ply:EyePos()
		Pos.z = -Pos.z
		local Vel = Ply:GetVelocity() * 0.01
		local Ang = Ply:GetAimVector()
		local Up = Ply:GetAimVector():Angle():Up() * -1

		BASS.SetPosition(Pos, Vel, Ang, Up)
	end

	hook.Add("Think", "StreamRadio_BassReposition", StreamRadio_BassReposition )
end